using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Application.EventBus;
using Admin.NET.Application.Service.Electricity.Dto;
using Admin.NET.Application.Service.Water.Dto;
using Admin.NET.Core;
using Furion;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.EventBus;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using SqlSugar;
using Yitter.IdGenerator;

namespace Admin.NET.Application.Service.Electricity;

[ApiDescriptionSettings(new string[] { "业务应用" }, Order = 100)]
public class WaterService : IDynamicApiController, ITransient, IPrivateDependency
{
	/// <summary>
	/// 设备离线
	/// </summary>
	/// <param name="sn">序列号</param>
	/// <param name="type">类型，0电表，1网关</param>
	/// <returns></returns>
	public async Task MeterOffline(string sn, int type)
	{
		switch (type)
		{
		case 0:
		{
			SqlSugarRepository<WaterDevice> _contextold = App.GetService<SqlSugarRepository<WaterDevice>>();
			SimpleClient<WaterDevice> _context = _contextold.CopyNew();
			WaterDevice meter = await (from u in _context.Context.Queryable<WaterDevice>()
				where u.Sn == sn && u.ProtocolType == 0
				select u).FirstAsync();
			if (meter != null)
			{
				meter.IsOnline = 0;
				meter.LastOnlineTime = DateTime.Now;
				DateTime dateTime = DateTime.Now;
				EarlyWarning earlyWarning = new EarlyWarning
				{
					TenantId = meter.TenantId,
					CreateTime = dateTime,
					Status = 0,
					IsDelete = false,
					WarningId = meter.Id,
					WarningTarget = meter.Sn,
					WarningTargetType = 1,
					WarningType = 1,
					WarningMsg = $"当前水表{meter.WaterName}，设备编号{meter.Sn}已离线"
				};
				await _context.Context.Updateable(meter).UpdateColumns((WaterDevice u) => new { u.IsOnline, u.LastOnlineTime }).ExecuteCommandAsync();
				await _context.Context.Insertable<WaterDevice>(earlyWarning).ExecuteCommandAsync();
			}
			break;
		}
		case 1:
		{
			SqlSugarRepository<Admin.NET.Application.Collector> _contextold = App.GetService<SqlSugarRepository<Admin.NET.Application.Collector>>();
			SimpleClient<Admin.NET.Application.Collector> _context = _contextold.CopyNew();
			Admin.NET.Application.Collector collectors = await (from u in _context.Context.Queryable<Admin.NET.Application.Collector>()
				where u.Imei == sn
				select u).FirstAsync();
			if (collectors != null)
			{
				collectors.Status = 0;
				collectors.LastOnlineTime = DateTime.Now;
				DateTime dateTime = DateTime.Now;
				EarlyWarning earlyWarning = new EarlyWarning
				{
					TenantId = collectors.TenantId,
					CreateTime = dateTime,
					Status = 0,
					IsDelete = false,
					WarningId = collectors.Id,
					WarningTarget = collectors.Imei,
					WarningTargetType = 1,
					WarningType = 1,
					WarningMsg = $"当前采集器{collectors.Name}，设备编号{collectors.Imei}已离线"
				};
				await _context.Context.Updateable(collectors).UpdateColumns((Admin.NET.Application.Collector u) => new { u.Status, u.LastOnlineTime }).ExecuteCommandAsync();
				await (from u in _context.Context.Updateable<WaterDevice>()
					where u.CollectorId == (long?)collectors.Id
					select u).SetColumns((WaterDevice u) => u.IsOnline == 0).SetColumns((WaterDevice u) => u.LastOnlineTime == DateTime.Now).ExecuteCommandAsync();
				await _context.Context.Insertable(earlyWarning).ExecuteCommandAsync();
			}
			break;
		}
		}
	}

	/// <summary>
	/// 设备在线
	/// </summary>
	/// <param name="sn">序列号</param>
	/// <param name="type">类型，0电表，1网关</param>
	/// <param name="upload">上报的数据</param>
	/// <param name="rssi">信号强度</param>
	/// <returns></returns>
	public async Task MeterOnline(string sn, int type, UploadFirstDto upload, int? rssi)
	{
		switch (type)
		{
		case 0:
		{
			SqlSugarRepository<WaterDevice> _contextold = App.GetService<SqlSugarRepository<WaterDevice>>();
			SimpleClient<WaterDevice> _context = _contextold.CopyNew();
			WaterDevice meter = await (from u in _context.Context.Queryable<WaterDevice>()
				where u.Sn == sn
				select u).FirstAsync();
			if (meter != null)
			{
				meter.IsOnline = 1;
				meter.LastOnlineTime = DateTime.Now;
				meter.RSSI = rssi;
				await _context.Context.Updateable(meter).UpdateColumns((WaterDevice u) => new { u.IsOnline, u.LastOnlineTime, u.RSSI }).ExecuteCommandAsync();
			}
			break;
		}
		case 1:
		{
			SqlSugarRepository<Admin.NET.Application.Collector> _contextold = App.GetService<SqlSugarRepository<Admin.NET.Application.Collector>>();
			SimpleClient<Admin.NET.Application.Collector> _context = _contextold.CopyNew();
			Admin.NET.Application.Collector collectors = await (from u in _context.Context.Queryable<Admin.NET.Application.Collector>()
				where u.Imei == sn
				select u).FirstAsync();
			if (collectors != null)
			{
				collectors.Status = 1;
				collectors.LastOnlineTime = DateTime.Now;
				collectors.Latitude = upload.lat;
				collectors.Longitude = upload.lng;
				collectors.RSSI = rssi;
				await _context.Context.Updateable(collectors).UpdateColumns((Admin.NET.Application.Collector u) => new { u.Status, u.LastOnlineTime, u.Latitude, u.Longitude, u.RSSI }).ExecuteCommandAsync();
				if (upload.device == null || upload.device.Count() <= 0)
				{
				}
			}
			break;
		}
		}
	}

	/// <summary>
	/// 设备预警，不一定通用
	/// </summary>
	/// <param name="sn">序列号</param>
	/// <param name="type">0电表，1网关</param>
	/// <param name="upload"></param>
	/// <returns></returns>
	public async Task MeterAlarm(string sn, int type, UploadAlarm upload)
	{
		SqlSugarRepository<EarlyWarning> _contextold = App.GetService<SqlSugarRepository<EarlyWarning>>();
		SimpleClient<EarlyWarning> _context = _contextold.CopyNew();
		switch (type)
		{
		case 0:
		{
			WaterDevice meter = await (from u in _context.Context.Queryable<WaterDevice>()
				where u.Sn == sn
				select u).FirstAsync();
			DateTime dateTime = DateTime.Now;
			if (meter != null)
			{
				EarlyWarning earlyWarning = new EarlyWarning
				{
					TenantId = meter.TenantId,
					CreateTime = dateTime,
					Status = 0,
					IsDelete = false,
					WarningId = meter.Id,
					WarningTarget = meter.Sn,
					WarningTargetType = 0,
					WarningType = 0,
					Type = 1
				};
				earlyWarning.WarningMsg = $"当前水表{meter.WaterName}，设备编号{meter.Sn}已断电";
				meter.WaterState = 0;
				await _context.Context.Updateable(meter).UpdateColumns((WaterDevice u) => new { u.WaterState }).ExecuteCommandAsync();
				await _context.Context.Insertable(earlyWarning).ExecuteCommandAsync();
			}
			break;
		}
		case 1:
		{
			Admin.NET.Application.Collector collectors = await (from u in _context.Context.Queryable<Admin.NET.Application.Collector>()
				where u.Imei == sn
				select u).FirstAsync();
			DateTime dateTime = DateTime.Now;
			if (collectors == null)
			{
				break;
			}
			EarlyWarning earlyWarning = new EarlyWarning
			{
				TenantId = collectors.TenantId,
				CreateTime = dateTime,
				Status = 0,
				IsDelete = false,
				WarningId = collectors.Id,
				WarningTarget = collectors.Imei,
				WarningTargetType = 1,
				WarningType = 0,
				Type = 1
			};
			WaterDevice meterInfo = await (from u in _context.Context.Queryable<WaterDevice>()
				where u.LowAddr == upload.Device && u.CollectorId == (long?)collectors.Id
				select u).FirstAsync();
			if (meterInfo != null)
			{
				earlyWarning.WarningId = meterInfo.Id;
				earlyWarning.WarningTarget = meterInfo.Sn;
				earlyWarning.WarningMsg = $"当前水表{meterInfo.WaterName}，编号{meterInfo.Sn}已断电";
				earlyWarning.WarningTargetType = 0;
				meterInfo.WaterState = 0;
				await _context.Context.Updateable(meterInfo).UpdateColumns((WaterDevice u) => new { u.WaterState }).ExecuteCommandAsync();
			}
			else
			{
				earlyWarning.WarningMsg = $"当前采集网关{collectors.Name}，编号{collectors.Imei}下属电表编号{upload.Device}已断电，但在系统无存档";
			}
			await _context.Context.Insertable(earlyWarning).ExecuteCommandAsync();
			break;
		}
		}
	}

	public async Task WaterUpload(string sn, int type, Dictionary<string, WaterInfoMqttDto> info)
	{
		string deviceKey = "";
		if (info != null && info.Count > 0)
		{
			deviceKey = info.Keys.First();
		}
		SqlSugarRepository<WaterDevice> _contextold = App.GetService<SqlSugarRepository<WaterDevice>>();
		SimpleClient<WaterDevice> _context = _contextold.CopyNew();
		SqlSugarRepository<WaterConsumptionRecord> _contextTwoold = App.GetService<SqlSugarRepository<WaterConsumptionRecord>>();
		SimpleClient<WaterConsumptionRecord> _contextTwo = _contextTwoold.CopyNew();
		if (_context == null)
		{
			return;
		}
		try
		{
			_context.Context.CurrentConnectionConfig.IsAutoCloseConnection = false;
			_contextTwo.Context.CurrentConnectionConfig.IsAutoCloseConnection = false;
			await _context.Context.Ado.BeginTranAsync();
			await _contextTwo.Context.Ado.BeginTranAsync();
			WaterDevice meterInfo = null;
			Admin.NET.Application.Collector collector = null;
			switch (type)
			{
			case 0:
				meterInfo = await (from u in _context.Context.Queryable<WaterDevice>()
					where u.IsDelete == false && u.Sn == sn
					select u).FirstAsync();
				meterInfo.IsOnline = 1;
				break;
			case 1:
				collector = await (from u in _context.Context.Queryable<Admin.NET.Application.Collector>()
					where u.Imei == sn
					select u).FirstAsync();
				if (collector == null)
				{
					return;
				}
				meterInfo = await (from u in _context.Context.Queryable<WaterDevice>()
					where u.IsDelete == false
					select u).WhereIF(collector != null, (WaterDevice u) => u.LowAddr == deviceKey && u.CollectorId == (long?)collector.Id).FirstAsync();
				meterInfo.IsOnline = 1;
				break;
			}
			WaterInfoMqttDto upload = info[deviceKey];
			decimal all = default(decimal);
			bool isSucess = decimal.TryParse(upload.Value, out all);
			decimal multiplier = meterInfo.Multiplier;
			all *= multiplier;
			if (!isSucess)
			{
				if (type == 1)
				{
					collector.Status = 1;
					collector.LastOnlineTime = DateTime.Now;
					_context.Context.Updateable(collector).UpdateColumns((Admin.NET.Application.Collector u) => new { u.Status, u.LastOnlineTime }).ExecuteCommand();
				}
				if (meterInfo != null)
				{
					meterInfo.IsOnline = 0;
					_context.Context.Updateable(meterInfo).UpdateColumns((WaterDevice u) => new { u.IsOnline }).ExecuteCommand();
				}
				return;
			}
			WaterConsumptionRecord powerConsumption;
			Room roomInfo;
			IUpdateable<Room> updateRoom;
			WarningRule waring;
			decimal nowBalance;
			int num4;
			if (meterInfo != null)
			{
				powerConsumption = new WaterConsumptionRecord
				{
					Sn = meterInfo.Sn,
					BuildingId = meterInfo.BuildingId.GetValueOrDefault(),
					RoomId = meterInfo.RoomId.GetValueOrDefault(),
					Name = meterInfo.WaterName,
					CollectorId = meterInfo.CollectorId.GetValueOrDefault(),
					TenantId = meterInfo.TenantId,
					UpdateUserName = meterInfo.UpdateUserName,
					CreateTime = DateTime.Now,
					IsDelete = false,
					MeterId = meterInfo.Id
				};
				roomInfo = null;
				if (meterInfo.RoomId.HasValue)
				{
					roomInfo = await (from u in _context.Context.Queryable<Room>()
						where (long?)u.Id == meterInfo.RoomId
						select u).FirstAsync();
				}
				WaterPriceRule ruleInfo = null;
				if (meterInfo.PriceRuleId.HasValue)
				{
					ruleInfo = await (from u in _context.Context.Queryable<WaterPriceRule>()
						where (long?)u.Id == meterInfo.PriceRuleId
						select u).FirstAsync();
				}
				decimal totalcheck = all - (meterInfo?.TotalUsage).GetValueOrDefault();
				powerConsumption.Id = YitIdHelper.NextId();
				powerConsumption.PositiveDosage = all;
				decimal allfee = default(decimal);
				if (ruleInfo != null)
				{
					allfee = totalcheck * ruleInfo.Price.GetValueOrDefault();
					powerConsumption.Price = ruleInfo.Price.GetValueOrDefault();
					powerConsumption.PriceRuleId = ruleInfo.Id;
				}
				powerConsumption.Amount = allfee;
				if (collector != null)
				{
					collector.Status = 1;
					collector.LastOnlineTime = DateTime.Now;
					_context.Context.Updateable(collector).UpdateColumns((Admin.NET.Application.Collector u) => new { u.Status, u.LastOnlineTime }).ExecuteCommand();
				}
				powerConsumption.TotalUsage = all;
				powerConsumption.PositiveDosage = all;
				powerConsumption.TotalUsageDifference = totalcheck;
				powerConsumption.PositiveDosageDifference = totalcheck;
				meterInfo.WaterState = ((!(upload.State == "0")) ? 1 : 0);
				meterInfo.TotalUsage = all;
				meterInfo.PositiveDosage = all;
				meterInfo.LatestMeterReadingTime = DateTime.Now;
				if (roomInfo != null)
				{
					updateRoom = from u in _context.Context.Updateable<Room>()
						where u.Id == roomInfo.Id
						select u;
					powerConsumption.RoomId = roomInfo.Id;
					powerConsumption.BuildingId = roomInfo.BuildingId;
					decimal can_deduct_fee = allfee;
					if (allfee != 0m)
					{
						RoomService _roomService = App.GetService<RoomService>();
						string msg = "用水结算";
						await _roomService.AddRoomBalanceRecord(_contextTwo.Context, roomInfo.Id, powerConsumption.Id, 1, -allfee, roomInfo.TenantId.Value, msg);
					}
					updateRoom = updateRoom.SetColumns((Room u) => u.Balance == u.Balance - allfee);
					if (roomInfo.WarningRuleId.HasValue)
					{
						waring = await (from u in _context.Context.Queryable<WarningRule>()
							where (long?)u.Id == roomInfo.WarningRuleId
							select u).FirstAsync();
						if (waring != null)
						{
							if (waring.IsDelete)
							{
							}
							nowBalance = roomInfo.Balance - can_deduct_fee;
							decimal num = nowBalance;
							decimal? firstThreshold = waring.FirstThreshold;
							if ((num <= firstThreshold.GetValueOrDefault()) & firstThreshold.HasValue)
							{
								if (!roomInfo.LatestWarningBalance.HasValue)
								{
									goto IL_1622;
								}
								if (roomInfo.LatestWarningBalance > waring.SecondThreshold)
								{
									decimal num2 = nowBalance;
									decimal? secondThreshold = waring.SecondThreshold;
									if ((num2 < secondThreshold.GetValueOrDefault()) & secondThreshold.HasValue)
									{
										goto IL_1622;
									}
								}
								if (roomInfo.LatestWarningBalance < waring.SecondThreshold && roomInfo.LatestWarningBalance > waring.LastThreshold)
								{
									decimal num3 = nowBalance;
									decimal? secondThreshold = waring.LastThreshold;
									num4 = (((num3 < secondThreshold.GetValueOrDefault()) & secondThreshold.HasValue) ? 1 : 0);
								}
								else
								{
									num4 = 0;
								}
								goto IL_1623;
							}
							goto IL_19fc;
						}
					}
					goto IL_1c08;
				}
				if (collector != null)
				{
					collector.Status = 1;
					collector.LastOnlineTime = DateTime.Now;
					_context.Context.Updateable(collector).UpdateColumns((Admin.NET.Application.Collector u) => new { u.Status, u.LastOnlineTime }).ExecuteCommand();
				}
				goto IL_1d36;
			}
			goto IL_1fb4;
			IL_1623:
			if (num4 != 0 && roomInfo.OwnerId.HasValue)
			{
				Owner owner = await (from u in _context.Context.Queryable<Owner>()
					where (long?)u.Id == roomInfo.OwnerId
					select u).FirstAsync();
				if (owner != null && !string.IsNullOrEmpty(owner.PhoneNumber))
				{
					decimal newBalance = Math.Round(nowBalance, 2);
					BillNoticePayload billNoticePayload = new BillNoticePayload
					{
						Body = $"您的房间：{roomInfo.Name}余额不足，剩余{newBalance}元，请及时充值。",
						Subject = "余额不足提醒",
						Remark = "若已充值，请忽略",
						Owners = new List<Owner> { owner },
						RoomId = roomInfo.Id,
						RoomName = roomInfo.Name,
						Balance = newBalance,
						Path = "/userPage/roomDetail/roomDetail?meterId=" + roomInfo.Id
					};
					EventPayload payload = new EventPayload
					{
						Data = JsonConvert.SerializeObject(billNoticePayload),
						TenantId = roomInfo.TenantId.Value
					};
					for (int i = 0; i < 4; i++)
					{
						MessageCenter.PublishAsync($"{i}:SendEarlyWarningNotice", payload).Wait();
					}
					updateRoom = updateRoom.SetColumns((Room u) => u.LatestWarningBalance == (decimal?)nowBalance);
				}
			}
			goto IL_19fc;
			IL_1c08:
			await updateRoom.ExecuteCommandAsync();
			goto IL_1d36;
			IL_19fc:
			int num5;
			if (waring.AllowOverdrawLimit.HasValue && nowBalance <= 0m)
			{
				decimal value = nowBalance;
				decimal? firstThreshold = waring.AllowOverdrawLimit;
				decimal? secondThreshold = (decimal?)value + firstThreshold;
				if ((secondThreshold.GetValueOrDefault() <= default(decimal)) & secondThreshold.HasValue)
				{
					num5 = ((upload.State == "0000") ? 1 : 0);
					goto IL_1aa8;
				}
			}
			num5 = 0;
			goto IL_1aa8;
			IL_1fb4:
			await _context.Context.Ado.CommitTranAsync();
			await _contextTwo.Context.Ado.CommitTranAsync();
			goto end_IL_01be;
			IL_1622:
			num4 = 1;
			goto IL_1623;
			IL_1d36:
			if (powerConsumption != null)
			{
				powerConsumption.IsDelete = false;
				await _contextTwo.InsertAsync(powerConsumption);
			}
			_context.Context.Updateable(meterInfo).UpdateColumns((WaterDevice u) => new { u.WaterState, u.IsOnline, u.TotalUsage, u.PositiveDosage, u.LatestMeterReadingTime }).ExecuteCommand();
			goto IL_1fb4;
			IL_1aa8:
			if (num5 != 0)
			{
				try
				{
					ElectricityService service = App.GetService<ElectricityService>();
					InputSwitch item = new InputSwitch
					{
						Id = meterInfo.Id,
						GateStatus = 1
					};
					await service.SwitchMeter(item, meterInfo.TenantId);
				}
				catch (Exception)
				{
				}
			}
			goto IL_1c08;
			end_IL_01be:;
		}
		catch (Exception)
		{
			await _context.Context.Ado.RollbackTranAsync();
			await _contextTwo.Context.Ado.RollbackTranAsync();
		}
		finally
		{
			_context.Context.Dispose();
			_contextTwo.Context.Dispose();
		}
	}

	private bool TimeCompareMonth(DateTime? tOne, DateTime tTwo)
	{
		if (!tOne.HasValue)
		{
			return false;
		}
		return tOne?.Year == tTwo.Year && tOne?.Month == tTwo.Month;
	}

	private bool TimeCompare(DateTime tOne, DateTime tTwo)
	{
		return (tOne - tTwo).TotalSeconds == 0.0;
	}

	private decimal ChangeDataToD(string strData)
	{
		decimal dData = default(decimal);
		if (strData.ToLower().Contains("e"))
		{
			decimal d = decimal.Parse(strData, NumberStyles.Float);
			CultureInfo cultureInfo = new CultureInfo("cn");
			decimal.TryParse(strData, NumberStyles.Float, cultureInfo, out dData);
		}
		else
		{
			decimal.TryParse(strData, out dData);
		}
		return dData;
	}
}
